package com.phenix.mvp.base.multitype;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v4.widget.Space;
import android.util.SparseArray;

import com.orhanobut.logger.Logger;
import com.phenix.mvp.util.TUtil;

import java.util.ArrayList;
import java.util.Map;

import io.reactivex.Observable;


/**
 * @author  zhouphenix on 2017-1-8.
 */

public final class MultiTypePool implements TypePool {

    private static final String TAG = MultiTypePool.class.getSimpleName();
    private final ArrayList<Class<? extends BaseViewHolder>> mViewHolderClazzs;
    private final ArrayList<Class<?>> mDataTypeMap;
    private final SparseArray<Object> mTags;


    public MultiTypePool() {
        this.mViewHolderClazzs = new ArrayList<>();
        this.mDataTypeMap = new ArrayList<>();
        this.mTags = new SparseArray<>();
    }

    public MultiTypePool(int capacity) {
        this.mViewHolderClazzs = new ArrayList<>(capacity);
        this.mDataTypeMap = new ArrayList<>(capacity);
        this.mTags = new SparseArray<>(capacity);
    }

    @Override
    public void register(@NonNull Context context, @NonNull Class<? extends BaseViewHolder>... clazzs) {
        Observable.fromArray(clazzs).subscribe(clazz -> register(context, clazz));
    }

    @Override
    public ArrayList<Class<? extends BaseViewHolder>> getViewHolders() {
        return mViewHolderClazzs;
    }

    @Override
    public void setTag(@NonNull Class<? extends BaseViewHolder> clazz, Map<Integer, Object> tags) {
        mTags.put(mViewHolderClazzs.indexOf(clazz), tags);
    }

    @Override
    public Map<Integer, Object> getTag(@NonNull Class<? extends BaseViewHolder> clazz) {
        return (Map<Integer, Object>) mTags.get(mViewHolderClazzs.indexOf(clazz));
    }


    public void register(@NonNull Context context, @NonNull Class<? extends BaseViewHolder> clazz) {
        Class<?> dataClass = ((BaseViewHolder) TUtil.getInstance(clazz, new Space(context))).getTypeClass();
        if (mViewHolderClazzs.contains(clazz)){
            mDataTypeMap.add(mViewHolderClazzs.indexOf(clazz), dataClass);
            Logger.t(TAG).d("You have registered the " + clazz.getSimpleName() + " type. " +
                    "It will override the original provider.");
        }else{
            mViewHolderClazzs.add(clazz);
            mDataTypeMap.add(dataClass);
        }
    }

    @Override
    public void unregister(@NonNull Class<? extends BaseViewHolder> clazz) {
        if (mViewHolderClazzs.contains(clazz)){
            int index = mViewHolderClazzs.indexOf(clazz);
            mDataTypeMap.remove(index);
            mViewHolderClazzs.remove(clazz);
            Logger.t(TAG).d("You have unregistered the " + clazz.getSimpleName() + " type. ");
        }
    }

    @Override
    public int indexOf(@NonNull Class<?> clazz) {
        return mDataTypeMap.indexOf(clazz);
    }

    @Override
    public Class<?> getItemTypeByViewHolder(@NonNull Class<? extends BaseViewHolder> clazz) {
        return mDataTypeMap.get(mViewHolderClazzs.indexOf(clazz));
    }

    @Override
    public Class<? extends BaseViewHolder> getViewHolderByType(int type) {
        Class<? extends BaseViewHolder> clazz = mViewHolderClazzs.get(type);
        return clazz;
    }


    @Override
    public Class<? extends BaseViewHolder> getViewHolderByClass(Class<?> itemClass) {
        return mViewHolderClazzs.get(indexOf(itemClass));
    }

}
